ci(dx): guard public dev-facing functions have a JSDoc summary#715
Conversation
Adds scripts/check-dx-coverage.mjs — a TypeDoc walk over the chat/ag-ui/ langgraph/render public surfaces that fails when an exported function lacks a JSDoc summary (so the audited DX bar can't silently regress). Honors @internal as an escape hatch for spec-only/implementation exports. Wired as a step in the `library` CI job. Documented the one straggler it found (extractErrorMessage). Guard reports: "all 65 public functions across chat/ag-ui/langgraph/render have a JSDoc summary." Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Claude encountered an error after 2m 40s —— View job Review: ci(dx) — DX-coverage guard
Overall: solid addition. The concept is right, CI wiring is minimal and correct, and the
|
|
Claude finished @blove's task in 1m 31s —— View job PR Review
Overall this is a clean, well-scoped CI guard. Three minor observations: 1. Redundant const app = await Application.bootstrapWithPlugins({ ... });
app.options.addReader(new TSConfigReader()); // ← no-op
2. Redundant const app = await Application.bootstrapWithPlugins({
excludeInternal: true, // ← already strips @internal symbols
...
});
// ...
if (isInternal(ref, ref.signatures?.[0])) continue; // ← never trueBecause 3. Return description left empty in The diff updates No correctness bugs, security issues, or type-safety problems found. The CI step has no shell injection risk (hardcoded |
| process.exit(1); | ||
| } | ||
|
|
||
| console.log(`✓ DX-coverage: all ${checked} public functions across chat/ag-ui/langgraph/render have a JSDoc summary.`); |
There was a problem hiding this comment.
Silent pass when checked === 0 — if TypeDoc converts successfully but finds no Function reflections (e.g. after a future refactor to arrow-function exports), this line prints "all 0 public functions" and exits 0, certifying nothing.
Add a floor check so a zero-function result is treated as a misconfiguration:
| console.log(`✓ DX-coverage: all ${checked} public functions across chat/ag-ui/langgraph/render have a JSDoc summary.`); | |
| if (!violations.length && checked === 0 && process.exitCode !== 1) { | |
| console.error('✗ DX-coverage: no public functions found — check entry points or entryPointStrategy.'); | |
| process.exit(1); | |
| } | |
| if (violations.length) { |
| excludeInternal: true, | ||
| ...(libTsconfig ? { tsconfig: libTsconfig } : {}), | ||
| }); | ||
| app.options.addReader(new TSConfigReader()); |
There was a problem hiding this comment.
app.options.addReader(new TSConfigReader()) is dead code here — bootstrapWithPlugins already runs the full option-reading pipeline (including TSConfig loading) before it returns. Adding a reader after bootstrap has no effect because app.convert() doesn't re-read options. The tsconfig path is already explicitly threaded in via the tsconfig key above (line 64), so this line can be removed without changing behaviour.
| if (!project) throw new Error(`TypeDoc failed to convert ${lib.slug}`); | ||
|
|
||
| for (const ref of walk(project.children)) { | ||
| if (ref.kind !== ReflectionKind.Function) continue; |
There was a problem hiding this comment.
Arrow-function exports escape the guard. TypeDoc classifies export const foo = () => {} as ReflectionKind.Variable, not ReflectionKind.Function, so it's skipped here. No exported arrow functions exist in the four covered libraries today (verified), but the guard will silently not apply if one is added.
If you want to close this gap now or in a follow-up:
| if (ref.kind !== ReflectionKind.Function) continue; | |
| if (ref.kind !== ReflectionKind.Function && ref.kind !== ReflectionKind.Variable) continue; | |
| // Variables: only check if callable (has call signatures) – catches arrow-function exports | |
| if (ref.kind === ReflectionKind.Variable && !ref.type?.declaration?.signatures?.length) continue; |
Or at minimum add a comment noting the known limitation so future contributors know.
What
A CI guard that keeps the TypeScript DX bar (from the v0.0.52 audit) from regressing:
scripts/check-dx-coverage.mjsdoes a TypeDoc walk over the@threadplane/chat/ag-ui/langgraph/renderpublic surfaces and fails when an exported function lacks a JSDoc summary.@internal-tagged symbols are exempt (spec-only / implementation exports).Library — lint / test / buildjob (no new job, no extra runner).@example/param-doc enforcement can tighten later.Result
Found and fixed the one straggler on main (
extractErrorMessage— documented as a public utility). Guard now reports:Verification
node scripts/check-dx-coverage.mjs→ green locally; ci.yml YAML validated; chat builds green.🤖 Generated with Claude Code